﻿/*
Copyright � Edward Nutting 2013
Author: Edward Nutting 
Date: Jul 8 18:31 2013

URL: https://typescriptui.codeplex.com/
Modifications:
 - 8/Jul/13 : Initial version.

License: https://typescriptui.codeplex.com/license
*/

/// <reference path="SelectionWindow.ts" />
/// <reference path="ToggleIndicator.ts" />
/// <reference path="Label.ts" />
/// <reference path="Panel.ts" />
/// <reference path="../Interfaces/IDropDownBox.d.ts" />
/// <reference path="Control.ts" />

module TSUI.UI
{
    export class DropDownBox<T> extends Control implements IDropDownBox
    {
        OnSelectedIndexChange: Events.SelectedIndexChangeEvent = new Events.SelectedIndexChangeEvent();
        
        _InputContentPanel: IPanel;
        _UnderlyingTextBox: ILabel;
        _DropDownToggle: IToggleIndicator;

        Items: Collections.IList<IListItem<T>>;

        _SelectionWindow: ISelectionWindow<T>;

        constructor()
        {
            super();

            this._rootElement.addClass("DropDownBox");

            this._InputContentPanel = new Panel();
            this.Children.Add(this._InputContentPanel);

            this._UnderlyingTextBox = new Label();
            this._UnderlyingTextBox.Focusable(true);
            this._UnderlyingTextBox.OnFocus.Attach(new Events.FocusEventHandler(this._UnderlyingControl_OnFocus, this));
            this._UnderlyingTextBox.OnBlur.Attach(new Events.BlurEventHandler(this._UnderlyingControl_OnBlur, this));
            this._InputContentPanel.Children.Add(this._UnderlyingTextBox);

            this._DropDownToggle = new ToggleIndicatorLabel();
            this._DropDownToggle.SetIndicatorToOff();
            this._DropDownToggle.Focusable(false);
            this._DropDownToggle.OnClick.Attach(new Events.ClickEventHandler(this._DropDownToggle_OnClick, this));
            this._InputContentPanel.Children.Add(this._DropDownToggle);

            this.Focusable(true);
            
            this._SelectionWindow = new SelectionWindow();
            this._SelectionWindow.ContentPanel.OnSelectionMade.Attach(new Events.SelectionMadeEventHandler(this.SelectionWindow_OnSelectionMade, this));
            this._SelectionWindow.ContentPanel.OnSelectedIndexChange.Attach(new Events.SelectedIndexChangeEventHandler(this.SelectionWindow_OnSelectedIndexChanged, this));
            this._SelectionWindow.OnClose.Attach(new Events.CloseEventHandler(this.SelectionWindow_Close, this));
            this.Items = this._SelectionWindow.ContentPanel.Items;
            this._SelectionWindow.ConstructDOM($("body"));
        }
        
        _HandleFocusableSet(focusable: bool)
        {
            this._rootElement.removeAttr("tabindex");
        }

        _JustClosedItems: bool = false;
        SelectionWindow_Close(eventArgs: Events.CloseEventArgs)
        {
            this._JustClosedItems = true;
            this.Focus();
        }
        SelectionWindow_OnSelectionMade(eventArgs: Events.SelectionMadeEventArgs)
        {
            this.HideItems();
        }
        SelectionWindow_OnSelectedIndexChanged(eventArgs: Events.SelectedIndexChangeEventArgs)
        {
            this._UnderlyingTextBox.Text(this.Items.ElementAt(this.SelectedIndex()).Text());
            this.OnSelectedIndexChange.Invoke(new Events.SelectedIndexChangeEventArgs(this));
        }

        _HideItemsTimeout: number = -1;
        _IgnoreNextBlur:bool = false;
        _OnFocus(event: JQueryEventObject): void
        {
            super._OnFocus(event);
            preventTabKey = true;
            if (this._HideItemsTimeout !== -1)
            {
                clearTimeout(this._HideItemsTimeout);
                this._HideItemsTimeout = -1;
            }
            if (this.ActuallyEnabled())
            {
                if (!this._SelectionWindow.Visible() && !this._JustClosedItems)
                {
                    this._IgnoreNextBlur = true;
                    this.ShowItems();
                }
            }

            this._JustClosedItems = false;
        }
        _OnBlur(event: JQueryEventObject): void
        {
            if (!this._IgnoreNextBlur)
            {
                super._OnBlur(event);
                preventTabKey = false;
                if (this._HideItemsTimeout !== -1)
                {
                    clearTimeout(this._HideItemsTimeout);
                    this._HideItemsTimeout = -1;
                }
                if (this._SelectionWindow.Visible())
                {
                    var _this = this;
                    this._HideItemsTimeout = setTimeout(function ()
                    {
                        _this.HideItems();
                    }, 50);
                }
            }
            this._IgnoreNextBlur = false;
        }

        _DropDownToggle_OnClick(event: Events.ClickEventArgs)
        {
            this._UnderlyingTextBox.Focus();
            StopEvent(event.jqEvent);
        }
        _UnderlyingControl_OnFocus(eventArgs: Events.FocusEventArgs): void
        {
            this._OnFocus(eventArgs.jqEvent);
        }
        _UnderlyingControl_OnBlur(eventArgs: Events.BlurEventArgs): void
        {
            this._OnBlur(eventArgs.jqEvent);
        }

        SelectedIndex(value: number = null): number
        {
            return this._SelectionWindow.ContentPanel.SelectedIndex(value);
        }
        
        Focus(): void
        {
            this._UnderlyingTextBox.Focus();
        }
        Blur(): void
        {
            this._UnderlyingTextBox.Blur();
        }

        ShowItems(): void
        {
            this._SelectionWindow.PositionCenterWindow();
            this._SelectionWindow.Show();
            this._DropDownToggle.SetIndicatorToOn();
            this.AddClass("Open");
        }
        HideItems(): void
        {
            this._SelectionWindow.Hide();
            this._DropDownToggle.SetIndicatorToOff();
            this.RemoveClass("Open");
        }

        Enabled(value?: bool): bool
        {
            var result = super.Enabled(value);
            if (!result && this._SelectionWindow.Visible())
            {
                this.HideItems();
            }
            return result;
        }
    }
}